From 05bde9d8dd539af36ed99cf3a2b00933d15562b0 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 1 May 2015 15:34:08 -0400 Subject: [PATCH] GtkSearchEngine: Use all search engines Just using tracker does not work well if you are searching in non-indexed locations, such as git checkouts or network mounts. Ideally, we'd decide the 'best' engine to use for each location. Since that is not easy to do, just run them in parallel for now, which is the same strategy that nautilus uses. --- gtk/gtksearchengine.c | 218 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 209 insertions(+), 9 deletions(-) diff --git a/gtk/gtksearchengine.c b/gtk/gtksearchengine.c index 1ae5cc6f66..ec7865cd3e 100644 --- a/gtk/gtksearchengine.c +++ b/gtk/gtksearchengine.c @@ -31,6 +31,19 @@ #define HAVE_TRACKER 1 #endif +struct _GtkSearchEnginePrivate { + GtkSearchEngine *native; + gboolean native_running; + gchar *native_error; + + GtkSearchEngine *simple; + gboolean simple_running; + gchar *simple_error; + + gboolean running; + GHashTable *hits; +}; + enum { HITS_ADDED, @@ -42,11 +55,88 @@ enum static guint signals[LAST_SIGNAL]; -G_DEFINE_ABSTRACT_TYPE (GtkSearchEngine, _gtk_search_engine, G_TYPE_OBJECT); +G_DEFINE_TYPE_WITH_PRIVATE (GtkSearchEngine, _gtk_search_engine, G_TYPE_OBJECT); + +static void +set_query (GtkSearchEngine *engine, + GtkQuery *query) +{ + if (engine->priv->native) + _gtk_search_engine_set_query (engine->priv->native, query); + + if (engine->priv->simple) + _gtk_search_engine_set_query (engine->priv->simple, query); +} + +static void +start (GtkSearchEngine *engine) +{ + g_hash_table_remove_all (engine->priv->hits); + + if (engine->priv->native) + { + g_clear_pointer (&engine->priv->native_error, g_free); + _gtk_search_engine_start (engine->priv->native); + engine->priv->native_running = TRUE; + } + + if (engine->priv->simple) + { + g_clear_pointer (&engine->priv->simple_error, g_free); + _gtk_search_engine_start (engine->priv->simple); + engine->priv->simple_running = TRUE; + } + + engine->priv->running = TRUE; +} + +static void +stop (GtkSearchEngine *engine) +{ + if (engine->priv->native) + { + _gtk_search_engine_stop (engine->priv->native); + engine->priv->native_running = FALSE; + } + + if (engine->priv->simple) + { + _gtk_search_engine_stop (engine->priv->simple); + engine->priv->simple_running = FALSE; + } + + engine->priv->running = FALSE; + + g_hash_table_remove_all (engine->priv->hits); +} + +static void +finalize (GObject *object) +{ + GtkSearchEngine *engine = GTK_SEARCH_ENGINE (object); + + g_clear_object (&engine->priv->native); + g_free (engine->priv->native_error); + + g_clear_object (&engine->priv->simple); + g_free (engine->priv->simple_error); + + g_clear_pointer (&engine->priv->hits, g_hash_table_unref); + + G_OBJECT_CLASS (_gtk_search_engine_parent_class)->finalize (object); +} static void _gtk_search_engine_class_init (GtkSearchEngineClass *class) { + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = finalize; + + class->set_query = set_query; + class->start = start; + class->stop = stop; + signals[HITS_ADDED] = g_signal_new ("hits-added", G_TYPE_FROM_CLASS (class), @@ -90,33 +180,143 @@ _gtk_search_engine_class_init (GtkSearchEngineClass *class) static void _gtk_search_engine_init (GtkSearchEngine *engine) { + engine->priv = _gtk_search_engine_get_instance_private (engine); +} + +static void +hits_added (GtkSearchEngine *engine, + GList *hits, + gpointer data) +{ + GtkSearchEngine *composite = GTK_SEARCH_ENGINE (data); + GList *added, *l; + + added = NULL; + + if (engine == composite->priv->native) + g_debug ("Getting hits from native search engine"); + else if (engine == composite->priv->simple) + g_debug ("Getting hits from simple search engine"); + + for (l = hits; l; l = l->next) + { + gchar *hit = l->data; + + if (!g_hash_table_contains (composite->priv->hits, hit)) + { + hit = g_strdup (hit); + g_hash_table_add (composite->priv->hits, hit); + added = g_list_prepend (added, hit); + } + } + + if (added) + { + g_debug ("Passing hits on"); + _gtk_search_engine_hits_added (composite, added); + g_list_free (added); + } +} + +static void +update_status (GtkSearchEngine *engine) +{ + gboolean running; + + running = engine->priv->native_running || engine->priv->simple_running; + + if (running != engine->priv->running) + { + engine->priv->running = running; + + if (!running) + { + if (engine->priv->native_error) + _gtk_search_engine_error (engine, engine->priv->native_error); + else if (engine->priv->simple_error) + _gtk_search_engine_error (engine, engine->priv->simple_error); + else + _gtk_search_engine_finished (engine); + } + } +} + +static void +finished (GtkSearchEngine *engine, + gpointer data) +{ + GtkSearchEngine *composite = GTK_SEARCH_ENGINE (data); + + if (engine == composite->priv->native) + composite->priv->native_running = FALSE; + else if (engine == composite->priv->simple) + composite->priv->simple_running = FALSE; + + update_status (composite); +} + +static void +error (GtkSearchEngine *engine, + const gchar *message, + gpointer data) +{ + GtkSearchEngine *composite = GTK_SEARCH_ENGINE (data); + + if (engine == composite->priv->native) + { + g_free (composite->priv->native_error); + composite->priv->native_error = g_strdup (message); + composite->priv->native_running = FALSE; + } + else if (engine == composite->priv->simple) + { + g_free (composite->priv->native_error); + composite->priv->native_error = g_strdup (message); + composite->priv->simple_running = FALSE; + } + + update_status (composite); +} + +static void +connect_engine_signals (GtkSearchEngine *engine, + gpointer data) +{ + g_signal_connect (engine, "hits-added", G_CALLBACK (hits_added), data); + g_signal_connect (engine, "finished", G_CALLBACK (finished), data); + g_signal_connect (engine, "error", G_CALLBACK (error), data); } GtkSearchEngine * _gtk_search_engine_new (void) { - GtkSearchEngine *engine = NULL; + GtkSearchEngine *engine; + + engine = g_object_new (GTK_TYPE_SEARCH_ENGINE, NULL); #ifdef HAVE_TRACKER - engine = _gtk_search_engine_tracker_new (); - if (engine) + engine->priv->native = _gtk_search_engine_tracker_new (); + if (engine->priv->native) { g_debug ("Using Tracker search engine"); - return engine; + connect_engine_signals (engine->priv->native, engine); } #endif #ifdef GDK_WINDOWING_QUARTZ - engine = _gtk_search_engine_quartz_new (); - if (engine) + engine->priv->native = _gtk_search_engine_quartz_new (); + if (engine->priv->native) { g_debug ("Using Quartz search engine"); - return engine; + connect_engine_signals (engine->priv->native, engine); } #endif + engine->priv->simple = _gtk_search_engine_simple_new (); g_debug ("Using simple search engine"); - engine = _gtk_search_engine_simple_new (); + connect_engine_signals (engine->priv->simple, engine); + + engine->priv->hits = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); return engine; } -- 2.30.2